package com.idroc.storage.support;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;

import com.idroc.storage.IoBlock;
import com.idroc.storage.IoBlockFile;
import com.idroc.storage.StorageOptions;

/**
 * IO块文件
 * @author yuyoo (yuyoo4j@163.com)
 * @date 2010-3-26 下午05:59:36
 */
public class LocalIoBlockFile implements IoBlockFile {
	
	/**
	 * 文件ID
	 */
	private int fileId = 0;
			
	/**
	 * 文件名称
	 */
	private String fileName = null;
	
	/**
	 * 随机访问文件
	 */
	private RandomAccessFile raf = null;
	
	/**
	 * IO块文件的IO块大小
	 */
	private int blockSize = 0;
		
	/**
	 * 根据文件名创建IO块文件
	 * @param fileId -- 文件ID
	 * @param fileName -- 文件名
	 * @throws IOException -- io异常
	 */
	public LocalIoBlockFile(int fileId, String fileName, int blockSize) throws IOException {
		
		this.fileId = fileId;
		this.fileName = fileName;
		this.blockSize = blockSize;
		File f = new File(fileName);
		if (!f.exists()) {
			f.createNewFile();
		}
        raf = new RandomAccessFile(f, "rw");
	}
	
	/*
	 * 获取本地IO块文件ID
	 * @see com.idroc.storage.IoBlockFile#getId()
	 */
	public int getId() {
		
		return fileId;
	}

	/*
	 * 获取本地IO块文件名称
	 * @see com.idroc.storage.IoBlockFile#getName()
	 */
	public String getName() { 
		
		return fileName;
	}
 
	/*
	 * 将一个IO块写入文件
	 * @see com.idroc.storage.IoBlockFile#write(com.idroc.storage.IoBlock)
	 */
	public boolean write(IoBlock block) { 
		
		if (block.isDirty()) {
			return writeData(block.getOffset(), block.array(), block.arrayOffset(), block.size());
		} else {
			return true;
		}
	}
 
	/*
	 * 在offset读取一个IO块
	 * @see com.idroc.storage.IoBlockFile#read(long)
	 */
	public IoBlock read(long offset) {
		
		IoBlock block = new FileIoBlock(this, offset, blockSize);
		block.load(); // 加载数据
		return block;
	}

	/*
	 * 读取IO块数据
	 * @see com.idroc.storage.IoBlockFile#readData(long, byte[], int, int)
	 */
	public boolean readData(long offset, byte[] data, int start, int length) {

		try {
			raf.seek(offset);
			int remaining = length;
			int pos = 0;
			while (remaining > 0) {
				int read = raf.read(data, start + pos, remaining);
				if (read == -1 && remaining > 0) {
					String errorMsg = "无法读取更多的数据, 存在" + remaining + "个字节未能读入";
					throw new IOException(errorMsg);
				}
				remaining -= read;
				pos += read;
			}
		} catch (Exception ex) {
			throw new RuntimeException("读取文件IO块异常", ex);
		} 	
		return true;
	}

	/*
	 * 写入IO块的数据
	 * @see com.idroc.storage.IoBlockFile#writeData(long, byte[], int, int)
	 */
	public boolean writeData(long offset, byte[] data, int start, int length) {
		
		try {
			raf.seek(offset);
			raf.write(data, start, length);
		} catch (Exception ex) {
			throw new RuntimeException("写入文件IO块异常", ex);
		}
		return true;
	}

	/*
	 * 创建IO块
	 * @see com.idroc.storage.IoBlockFile#newIoBlock(long, byte[], int)
	 */
	public IoBlock newIoBlock(long offset, byte[] backend, int backendOffset) {
		
		IoBlock block = new FileIoBlock(this, offset, blockSize, backend, backendOffset); 
		return block;
	}

	/*
	 * 获取IO块文件中IO块的大小
	 * @see com.idroc.storage.IoBlockFile#getBlockSize()
	 */
	public int getBlockSize() {
		
		return blockSize;
	}
	
	@Override
	public String toString() {

		StringBuilder sb = new StringBuilder(256);
		sb.append("LocalIoBlockFile{");
		sb.append("fileId:").append(fileId).append(",");
		sb.append("fileName:").append(fileName).append(",");
		sb.append("raf:").append(raf).append(",");
		sb.append("}");
		
		return sb.toString();
	}
}
